﻿#define _CRT_SECURE_NO_WARNINGS

#define FMT_HEADER_ONLY
#define FMT_UNICODE 0
#include <fmt/core.h>
#include <fmt/ranges.h>

#include <thread>
#include <functional>
#include <sstream>
#include <chrono>

#include "workspace/workspace.hpp"
using namespace wsp;

void g(int idx)
{
    fmt::println("HanYa said hello world {}", idx);
}

int main()
{
    wsp::workbranch pond(8);

    for (int i=0; i < 10000; i++)
    {
        auto f = std::bind(
            [](int idx) {
                std::stringstream sin;
                sin << std::this_thread::get_id();
                fmt::println("[{:>6}] hello world {}", sin.str(), idx);
            },
            i);
        pond.submit(f);
    }

    // 带返回值的提交
    auto ret = pond.submit([] {
        return 2023;
    });
    fmt::println("task return {}", ret.get());

    // 主线程等待所有任务被执行
    pond.wait_tasks();

    {
        wsp::futures<int> futures;
        wsp::workspace    spc;
        spc.attach(new wsp::workbranch(2));
    

        for (int i = 0; i < 5; ++i)
        {
            futures.add_back(spc.submit([i] {
                return i + 1;
            }));
        }

        futures.wait();
        auto res = futures.get();
        for (auto& each : res)
        {
            fmt::println("task return {}", each);
        }
    }

	// supervisor
	// supervisor是异步管理者线程的抽象，负责监控workbranch的负载情况并进行动态调整。
	// 它允许你在每一次调控workbranch之后执行一个小任务，你可以用来写日志或者做一些其它调控等。

	// 每一个supervisor可以管理多个workbranch。此时workbranch之间共享supervisor的所有设定。
    {
        wsp::workbranch br1(2);
        wsp::workbranch br2(2);

        // 2 <= thread number <= 4
        // time interval: 1000 ms
        wsp::supervisor sp(2, 4, 1000);

        sp.set_tick_cb([&br1, &br2] {
            auto        now        = std::chrono::system_clock::now();
            std::time_t timestamp  = std::chrono::system_clock::to_time_t(now);
            std::tm     local_time = *std::localtime(&timestamp);
            static char buffer[40];
            std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &local_time);
            std::cout << "[" << buffer << "] " << "br1: [workers] " << br1.num_workers() << " | [blocking-tasks] "
                      << br1.num_tasks() << '\n';
            std::cout << "[" << buffer << "] " << "br2: [workers] " << br2.num_workers() << " | [blocking-tasks] "
                      << br2.num_tasks() << '\n';
        });

        sp.supervise(br1);   // start supervising
        sp.supervise(br2);   // start supervising

        for (int i = 0; i < 1000; ++i)
        {
            br1.submit([] {
                std::this_thread::sleep_for(std::chrono::milliseconds(10));
            });
            br2.submit([] {
                std::this_thread::sleep_for(std::chrono::milliseconds(20));
            });
        }

        br1.wait_tasks();
        br2.wait_tasks();
    }
}
